8c0f079a516e8fe9c7e98eceb948875a63e4b0ed,governator-core/src/main/java/com/netflix/governator/ScanningModuleBuilder.java,ScanningModuleBuilder,build,#,137

Before Change


        // Generate the list of elements here and immediately create a module from them.  This ensures
        // that the class path is canned only once as a Module's configure method may be called multiple
        // times by Guice.
        return Elements.getModule(Elements.getElements(new AbstractModule() {
            @Override
            public void configure() {
                for ( String basePackage : packages )  {
                    try {
                        String basePackageWithSlashes = basePackage.replace(".", "/");
                        for (URL url : Collections.list(classLoader.getResources(basePackageWithSlashes))) {
                            try {
                                if ( isJarURL(url)) {
                                    String jarPath = url.getFile();
                                    if ( jarPath.contains("!") ) {
                                        jarPath = jarPath.substring(0, jarPath.indexOf("!"));
                                        url = new URL(jarPath);
                                    }
                                    File file = ClasspathUrlDecoder.toFile(url);
                                    try (JarFile jar = new JarFile(file)) {
                                        for (JarEntry entry : Collections.list(jar.entries())) {
                                            try {
                                                if ( entry.getName().endsWith(".class") && entry.getName().startsWith(basePackageWithSlashes)) {
                                                    try (InputStream is = jar.getInputStream(entry)) {
                                                        handleClass(is);
                                                    }
                                                }
                                            } catch (Exception e) {
                                                addError("Unable to scan JarEntry '%s' in '%s'. %s", entry.getName(), file.getCanonicalPath(), e.getMessage());
                                                addError(e);
                                            }
                                        }
                                    } catch (Exception e ) {
                                        addError("Unable to scan '%s'. %s", file.getCanonicalPath(), e.getMessage());
                                        addError(e);
                                    }
                                } else {
                                    DirectoryClassFilter filter = new DirectoryClassFilter(classLoader);
                                    for ( String className : filter.filesInPackage(url, basePackage) ) {
                                        try (InputStream is = filter.bytecodeOf(className)) {
                                            handleClass(is);
                                        }
                                    }
                                }
                            } catch (Exception e) {
                                addError("Unable to scan jar '%s'. %s ", url, e.getMessage());
                                addError(e);
                            }
                        }
                    } catch ( Exception e ) {
                        addError("Classpath scanning failed for package \'" + basePackage + "\'");
                        addError(e);
                    }
                }
            }
            
            private boolean isJarURL(URL url) {
                String protocol = url.getProtocol();
                return "zip".equals(protocol) || "jar".equals(protocol) ||
                        ("file".equals(protocol) && url.getPath().endsWith(".jar"));
            }
            
            private void handleClass(InputStream inputStream) throws IOException {
                new ClassReader(inputStream).accept(new ClassVisitor(Opcodes.ASM5) {
                    private String className;
                    
                    @Override
                    public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
                        className = name.replace('/', '.');
                        super.visit(version, access, name, signature, superName, interfaces);
                    }
                    
                    @Override
                    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
                        Type type = getType(desc);
                        if (includeRule.apply(className)) {
                            for (AnnotatedClassScanner scanner : scanners) {
                                if (getType(scanner.annotationClass()).equals(type)) {
                                    try {
                                        Class<?> cls = Class.forName(className, false, classLoader);
                                        scanner.applyTo(binder(), cls.getAnnotation(scanner.annotationClass()), Key.get(cls));
                                    } catch (ClassNotFoundException e) {
                                        binder().addError(e);
                                        binder().addError("Failed process scanned class %s", className);
                                    }
                                }
                            }
                        }
                        
                        return super.visitAnnotation(desc, visible);
                    }
                }, SKIP_CODE);
            }
        }));
    };
}

After Change


        // Generate the list of elements here and immediately create a module from them.  This ensures
        // that the class path is canned only once as a Module's configure method may be called multiple
        // times by Guice.
        return Elements.getModule(Elements.getElements(new AbstractModule() {
            @Override
            public void configure() {
                final ClassPath classPath;
                try {
                    classPath = ClassPath.from(classLoader);
                } catch (IOException e) {
                    this.addError(e);
                    return;
                }
                
                for (ClassInfo classInfo : classPath.getAllClasses()) {
                    if (!isInTargetPackages(classInfo.getPackageName()) || !includeRule.apply(classInfo.getName())) {
                        continue;
                    }
                    
                    for (AnnotatedClassScanner scanner : scanners) {
                        Class<?> cls = classInfo.load();
                        if (cls.isAnnotationPresent(scanner.annotationClass())) {
                            try {
                                scanner.applyTo(binder(), cls.getAnnotation(scanner.annotationClass()), Key.get(cls));
                            } catch (Exception e) {
                                binder().addError("Failed process scanned class %s", classInfo.getName());
                                binder().addError(e);
                            }
                        }
                    }
                }
            }
        }));
    };
}